package com.hexacta.hrs.web.util;

import java.sql.Connection;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.sql.DataSource;

import org.apache.commons.lang.StringUtils;

import com.hexacta.hrs.Version;
import com.hexacta.tools.db.SchemaVersionChecker;

/**
 * This database listener checks that the database schema version matches the
 * expected version expected by the code.
 * 
 * @author tpollak
 */
public class DatabaseListener implements ServletContextListener {

    @Override
    public void contextDestroyed(final ServletContextEvent arg0) {
        // Nothing to do
    }

    @Override
    public void contextInitialized(final ServletContextEvent event) {
        ServletContext servletContext = event.getServletContext();
        Connection connection = openConnection(servletContext);
        try {
            checkSchemaVersion(connection, servletContext);
        } finally {
            closeConnection(servletContext, connection);
        }
    }

    private void checkSchemaVersion(final Connection connection, final ServletContext servletContext) {
        SchemaVersionChecker checker = new SchemaVersionChecker(connection, "system_constant", "code", "value",
                "system.version");
        servletContext.log("Checking Schema Version...");
        String currentVersion = Version.SCHEMA_VERSION;

        // Se elimina el Snapshot final si se estuiese en ambiente de desarrollo
        // para que
        // Matchee con la version de la base
        currentVersion = StringUtils.removeEnd(currentVersion, "-SNAPSHOT");
        checker.assertSchemaVersion(currentVersion);
        servletContext.log("Schema Version Check: Ok");
    }

    private void closeConnection(final ServletContext servletContext, final Connection connection) {
        try {
            connection.close();
        } catch (SQLException e) {
            servletContext.log("Error closing connection", e);
        }
    }

    private Connection openConnection(final ServletContext servletContext) {
        try {
            servletContext.log("Fetching Datasource");
            Context context = new InitialContext();
            DataSource datasource = (DataSource) context.lookup("java:comp/env/jdbc/VectricsDb");
            Connection connection = datasource.getConnection();
            servletContext.log("Opened Connection");
            return connection;
        } catch (NamingException e) {
            throw new IllegalStateException(e);
        } catch (SQLException e) {
            throw new IllegalStateException(e);
        }
    }
}
